package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.business.Vo.RulePremiseVo;
import com.ruoyi.business.common.riskRule.RulePremiseService;
import com.ruoyi.business.common.riskRule.RuleStrategy;
import com.ruoyi.business.service.IAppService;
import com.ruoyi.business.service.IRaiseLimitService;
import com.ruoyi.business.service.RestTemplateService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.RiskConstants;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sms.domain.SmsSendData;
import com.ruoyi.sms.service.ISmsService;
import com.ruoyi.sms.service.impl.SmsServiceImpl;
import com.ruoyi.system.service.ISysConfigService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;

@Slf4j
@Service
@AllArgsConstructor
public class RaiseLimitServiceImpl extends BaseService implements IRaiseLimitService {

    private IAppService appService;

    private ICreditApplyService creditApplyService;

    private ICustReplenishInfoService replenishInfoService;

//    private RuleEngineService ruleEngineService;

    private ICreditAccountService creditAccountService;

    private ILoanOrderService loanOrderService;

    private ILoanIouService loanIouService;

    private ISmsService smsService;

    private ISmsTemplateService smsTemplateService;

    private ISmsTaskService smsTaskService;

    private ICustomerInfoService customerInfoService;

    private ISysConfigService configService;

    private RulePremiseService premiseService;

    private IIncreasedLimitLogService increasedLimitLogService;

    @Autowired
    private RestTemplateService restTemplateService;

    @Override
    public void replenishInfo(CustReplenishInfo replenishInfo) {
        CustomerInfo customerInfo = getCustomerInfo();
        if (!replenishInit(customerInfo, replenishInfo)) {
            throw new BusinessException("保存失败！");
        }
        //creditFlag通过
        RulePremiseVo rulePremiseVo = RulePremiseVo.builder().
                custNo(customerInfo.getCustNo()).type(RuleStrategy.REPLENISH).userId(getUserId()).
                serialNo(replenishInfo.getSerialNo()).fingerprint(replenishInfo.getDeviceInfo().getString("newFingerprint")).build();
        premiseService.rulePremiseV228(rulePremiseVo);
    }

    @Transactional
    public void replenishInfoPass(String custNo) {
        //规则引擎
        log.info("开始补充信息提额：{}", custNo);
        CustomerInfo customerInfo = getCustInfo(custNo);
        CustReplenishInfo replenishInfo = replenishInfoService.getOneByCustNo(custNo);
//        JSONObject ruleRst = ruleEngineService.riskRuleRaiseLimit(RiskConstants.RULE_TYPE_REPLENISH, customerInfo.getCustNo());
        JSONObject ruleRst = restTemplateService.riskRuleRaiseLimit(RiskConstants.RULE_TYPE_REPLENISH, customerInfo.getCustNo());
        String ruleResult = ruleRst.getString(RiskConstants.RULE_RESULT_DEAL_TYPE_KEY);
        BigDecimal adjustLimit = ruleRst.getBigDecimal(RiskConstants.RULE_RAISE_PASS_ADJUST_LIMIT);

        //非Accept Reject 未知结果
        if (!StringUtils.equalsAny(ruleResult, RiskConstants.RULE_RESULT_PASS,RiskConstants.RULE_RESULT_REJECT)) {
            return;
        }
        //更新客户信息
        customerInfoService.updateByReplenish(customerInfo,replenishInfo);

        //拒绝 状态更新 发送短信
        if (!RiskConstants.RULE_RESULT_PASS.equals(ruleResult)) {
            replenishInfoService.updateStatus(replenishInfo.getCustNo(), CustReplenishInfo.FAIL);
            sendSms(custNo, BizConstants.SMS_TYPE_INCR_RAISE_REJ, RiskConstants.RULE_TYPE_REPLENISH, BigDecimal.ZERO);
            return;
        }
        //更新补充信息状态
        replenishInfoService.updateStatus(replenishInfo.getCustNo(), CustReplenishInfo.PASS);
        //开始提额
        raiseLimitStart(customerInfo.getCustNo(), adjustLimit, RiskConstants.RULE_TYPE_REPLENISH);
    }

    @Async
    @Override
    @Transactional
    public void bindCardRaiseLimit(String custNo) {
        log.info("开始绑卡提额：{}", custNo);
        this.raiseLimitCheck(custNo);
        CustomerInfo customerInfo = getCustInfo(custNo);
        //调用规则引擎
//        JSONObject ruleRst = ruleEngineService.riskRuleRaiseLimit(RiskConstants.RULE_TYPE_BIND_CARD, customerInfo.getCustNo());
        JSONObject ruleRst = restTemplateService.riskRuleRaiseLimit(RiskConstants.RULE_TYPE_BIND_CARD, customerInfo.getCustNo());
        String ruleResult = ruleRst.getString(RiskConstants.RULE_RESULT_DEAL_TYPE_KEY);
        BigDecimal adjustLimit = ruleRst.getBigDecimal(RiskConstants.RULE_RAISE_PASS_ADJUST_LIMIT);

        //拒绝 状态更新 发送短信
        if (!RiskConstants.RULE_RESULT_PASS.equals(ruleResult)) {
            sendSms(custNo, BizConstants.SMS_TYPE_CARD_RAISE_REJ, RiskConstants.RULE_TYPE_BIND_CARD, BigDecimal.ZERO);
            return;
        }
        //开始提额
        raiseLimitStart(customerInfo.getCustNo(), adjustLimit, RiskConstants.RULE_TYPE_BIND_CARD);
    }

    @Override
    public void replenishInfoCheck() {
        //补充信息提额审批中
        CustReplenishInfo replenishInfo = replenishInfoService.getOneByCustNo(getCustNo());
        if (replenishInfo == null) {
            return;
        }
        if (replenishInfo.getState().equals(CustReplenishInfo.FAIL)) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_REPLENISH_FAIL);
        }
        if (replenishInfo.getState().equals(CustReplenishInfo.APPROVAL)) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_ADDITIONAL);
        }
        if (replenishInfo.getState().equals(CustReplenishInfo.PASS)) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_SUCCEED);
        }
    }

    @Override
    public void raiseLimitCheck(String custNo) {
        CustomerInfo customerInfo = getCustInfo(custNo);
        CreditApply creditApply = creditApplyService.getOneByCust(customerInfo.getCustNo());
        //未授信 or 授信审批中
        if (Func.isEmpty(creditApply) || StringUtils.equalsAny(creditApply.getApplyStatus().toString(), "9", "10", "11")) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_NOT_LIST);
        }
        //授信拒绝 or 授信成功但不能主动提额
        if (creditApply.getApplyStatus().equals(BizConstants.APPLY_STATUS_0_REFUSED) || "0".equals(customerInfo.getPromotion())) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_NOT_MEET);
        }
        //是否逾期
        int count = loanIouService.overdueIouCount(customerInfo.getCustNo());
        if (count > 0) {
            throw new BusinessException(RspEnmu.RAISE_LIMIT_HAVE_OVERDUE);
        }
    }


    //补充信息初始化
    private boolean replenishInit(CustomerInfo customerInfo, CustReplenishInfo replenishInfo) {
        replenishInfo.setUserId(customerInfo.getUserId());
        replenishInfo.setCustNo(customerInfo.getCustNo());
        replenishInfo.setState(CustReplenishInfo.APPROVAL);
        appService.saveAppDeviceInfo(customerInfo.getUserId(), customerInfo.getCustNo(), RiskConstants.RULE_TYPE_REPLENISH, replenishInfo.getSerialNo(), replenishInfo.getDeviceInfo());
        return replenishInfoService.save(replenishInfo);
    }


    //开始提额
    private void raiseLimitStart(String custNo, BigDecimal adjustLimit, String adjustType) {

        //额度更新
        int i = creditAccountService.updateCreditLine(adjustLimit, custNo, RiskConstants.RULE_TYPE_REPLENISH.equals(adjustType) ? "6" : "4");
        //发送审批通过短信
        if (i > 0) {
            //获取冻结期
            Date orderTime = new Date();
            int freezeDays = getFreezeDays(custNo, orderTime);
            BigDecimal latestQuota = creditAccountService.getLatestQuota(custNo);
            if (freezeDays > 0) {
                createTimedSMSTask(custNo, orderTime, freezeDays, adjustType, latestQuota);
            } else {
                sendSms(custNo, RiskConstants.RULE_TYPE_REPLENISH.equals(adjustType) ?
                                BizConstants.SMS_TYPE_INCR_RAISE_EFF : BizConstants.SMS_TYPE_CARD_RAISE_EFF,
                        adjustType, latestQuota);
            }
        }
    }

    //获取冻结期
    private int getFreezeDays(String custNo, Date orderTime) {

        int freeze = 0;
        LoanOrder loanOrder = loanOrderService.getOneByCustNo(custNo);
        if (Func.isNotEmpty(loanOrder)) {
            orderTime = loanOrder.getUpdateTime();
            freeze = getOrderFreeze(loanOrder.getFreezeDate(), loanOrder.getLoanStatus());
        }

        //无冻结期
        if (freeze <= 0 || orderTime == null) {
            //发送短信
            return 0;
        }
        //计算冻结期
        int creditRejectDays = DateUtils.daysBetween(orderTime, new Date());
        //在冻结期
        if (freeze - creditRejectDays > 0) {
            return freeze - creditRejectDays;
        }
        //无冻结期
        return 0;
    }

    private int getOrderFreeze(String freezeDate, Integer orderState) {
        if (LoanOrder.LOAN_STATUS_0_APPROVE_REFUSED == orderState && Func.isNotEmpty(freezeDate)) {
            return Integer.valueOf(freezeDate);
        }
        return 0;
    }

    private void sendSms(String custNo, String smsType, String adjustType, BigDecimal amount) {
        RealNameAuth realNameAuth = getRealNameByCustNo(custNo);
        AppUser appUser = getAppUser(realNameAuth.getUserId());

        JSONObject param = new JSONObject();
        param.put("lastName", realNameAuth.getLastName());
        param.put("type", adjustType);
        param.put("amount", Optional.ofNullable(amount).orElse(BigDecimal.ZERO).setScale(2));

        SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE)
                .phoneNumber(appUser.getPhone()).countryCode(appUser.getCountryCode())
                .smsParam(param).smsType(smsType).build();
        smsService.sendSms(smsData);
    }


    //创建定时短信任务
    private void createTimedSMSTask(String custNo, Date orderTime, int heaven, String adjustType, BigDecimal amount) {
        RealNameAuth realNameAuth = getRealNameByCustNo(custNo);
        AppUser appUser = getAppUser(realNameAuth.getUserId());
        //获取短信模版
        SmsTemplate smsTemplate = smsTemplateService.getByTemplateType(RiskConstants.RULE_TYPE_REPLENISH.equals(adjustType) ? BizConstants.SMS_TYPE_INCR_RAISE_UN_FREEZE : BizConstants.SMS_TYPE_CARD_RAISE_UN_FREEZE);

        JSONObject param = new JSONObject();
        param.put("lastName", realNameAuth.getLastName());
        param.put("type", adjustType);
        param.put("amount", Optional.ofNullable(amount).orElse(BigDecimal.ZERO).setScale(2));

        SmsTask smsTask = new SmsTask();
        smsTask.setUserId(realNameAuth.getUserId());
        smsTask.setCustNo(realNameAuth.getCustNo());
        smsTask.setCountryCode("+234");
        smsTask.setPhone(appUser.getPhone());
        smsTask.setNoticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE);
        smsTask.setSmsParam(JSON.toJSONString(param));
        smsTask.setSmsType(smsTemplate.getSmsType());
        String content = SmsServiceImpl.replaceTemplateParams(smsTemplate.getTemplateContent(), param);
        smsTask.setContent(content);
        smsTask.setIsTiming(1);
        smsTask.setScheduleTime(DateUtils.addDays(orderTime, heaven));
        smsTaskService.insertSmsTask(smsTask);
    }

    @Override
    public void contactCheck(CustReplenishInfo replenishInfo) {
        //获取授信记录
        String contactPhone = StringUtils.substringAfter(replenishInfo.getReplenishRelatePhone(), 10);
        //注册
        String registerPhone = StringUtils.substringAfter(getAppUser().getPhone(), 10);
        if (contactPhone.equals(registerPhone)) {
            throw new BusinessException(Func.isEmpty(replenishInfo.getJobTitle()) ? RspEnmu.RAISE_LIMIT_PHONE_REPEAT1 : RspEnmu.RAISE_LIMIT_PHONE_REPEAT2);
        }
        //bvn号码
        RealNameAuth realNameAuth = getRealNameAuth();
        String bvnPhone = StringUtils.substringAfter(realNameAuth.getPhoneNumber(), 10);
        if (contactPhone.equals(bvnPhone)) {
            throw new BusinessException(Func.isEmpty(replenishInfo.getJobTitle()) ? RspEnmu.RAISE_LIMIT_PHONE_REPEAT1 : RspEnmu.RAISE_LIMIT_PHONE_REPEAT2);
        }
        //联系人号码
        CreditApply creditApply = creditApplyService.getOneByCust(realNameAuth.getCustNo());
        String applyContactPhone = StringUtils.substringAfter(creditApply.getRelatePhone(), 10);
        if (applyContactPhone.equals(contactPhone)) {
            throw new BusinessException(Func.isEmpty(replenishInfo.getJobTitle()) ? RspEnmu.RAISE_LIMIT_PHONE_REPEAT1 : RspEnmu.RAISE_LIMIT_PHONE_REPEAT2);
        }
        if (Func.isNotEmpty(creditApply.getRelatePhone2())) {
            String applyContactPhone2 = StringUtils.substringAfter(creditApply.getRelatePhone2(), 10);
            if (applyContactPhone2.equals(contactPhone)) {
                throw new BusinessException(Func.isEmpty(replenishInfo.getJobTitle()) ? RspEnmu.RAISE_LIMIT_PHONE_REPEAT1 : RspEnmu.RAISE_LIMIT_PHONE_REPEAT2);
            }
        }

    }

    @Override
    public JSONObject getPromotionJson(String custNo) {
        JSONObject json = new JSONObject();
        json.put("replenishInfoAdjustConfig", configService.selectConfigByKey("replenishInfoAdjust"));
        json.put("bindCardAdjustConfig", configService.selectConfigByKey("bindCardAdjust"));
        json.put("replenishInfoAdjust", BigDecimal.ZERO);
        json.put("bindCardAdjust", BigDecimal.ZERO);
        json.put("replenishInfoStatus", CustReplenishInfo.NONE);
        if (Func.isNotEmpty(custNo)) {
            CustReplenishInfo replenishInfo = replenishInfoService.getOneByCustNo(custNo);
            json.put("replenishInfoStatus", Func.isEmpty(replenishInfo) ? CustReplenishInfo.NONE : replenishInfo.getState());
            BigDecimal bandCardIncreasedSum = increasedLimitLogService.increasedSumByType(custNo, Constants.RaiseLimit.ADJUST_TYPE_BANK_CARD);
            json.put("bindCardAdjust", Optional.ofNullable(bandCardIncreasedSum).orElse(BigDecimal.ZERO));
            BigDecimal replenishIncreasedSum = increasedLimitLogService.increasedSumByType(custNo, Constants.RaiseLimit.ADJUST_TYPE_REPLENISH_INFO);
            json.put("replenishInfoAdjust", Optional.ofNullable(replenishIncreasedSum).orElse(BigDecimal.ZERO));
        }
        return json;
    }


}
